package painting;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class GUI {
	private JLabel[][] board;
	// private boolean wait;
	private JFrame frame;
	private int[][] boardValues;
	private int xCord;
	private int yCord;
	boolean firstTime = true;

	public GUI() {
		// 1. Create the frame.
		// wait = false;

		frame = new JFrame("Robot Mapping");

		// 2. Optional: What happens when the frame closes?
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		JPanel things = new JPanel();
		GridLayout gl = new GridLayout(10, 10);
		things.setLayout(gl);

		board = new JLabel[10][10];
		boardValues = new int[10][10];
		for (int i = 0; i < 10; i++) {
			for (int j = 0; j < 10; j++) {
				board[i][j] = new JLabel();
				boardValues[i][j] = 7;

				board[i][j].setBackground(Color.GRAY);
				board[i][j].setVisible(true);
				board[i][j].setOpaque(true);
				things.add(board[i][j]);
			}
		}

		// 3. Create components and put them in the frame.
		// ...create emptyLabel...
		frame.getContentPane().add(things, BorderLayout.CENTER);
		frame.setPreferredSize(new Dimension(520, 550));

		// 4. Size the frame.
		frame.pack();

		// 5. Show it.
		frame.setVisible(true);

	}

	

	public void update() {

		for (int i = 0; i < 10; i++) {
			for (int j = 0; j < 10; j++) {
				if (board[i][j].getBackground() != Color.BLUE) {
					if (boardValues[i][j] > 7) {
						board[i][j].setBackground(Color.RED);
						String nbr = "" + boardValues[i][j];
						board[i][j].setText(nbr);
					} else if (boardValues[i][j] < 7) {
						board[i][j].setBackground(Color.GREEN);
						String nbr = "" + boardValues[i][j];
						board[i][j].setText(nbr);
					} else {
						board[i][j].setBackground(Color.GRAY);
						String nbr = "" + boardValues[i][j];
						board[i][j].setText(nbr);
					}
				}
			}

		}

		frame.pack();

	}

	public void updateSingelCell(int i, int j, Color c) {
		board[i][j].setBackground(c);
		frame.pack();

	}

	public void doMove(int i, int j) {

	}

	public void updateRobotPos(int xCord, int yCord, int xOldCord, int yOldCord) {
		this.xCord = xCord;
		this.yCord = yCord;
		//System.out.println(xCord + " " + yCord);
		//System.out.println("Old: " + xOldCord + " " + yOldCord);
		board[yOldCord][xOldCord].setBackground(Color.GREEN);
		boardValues[yOldCord][xOldCord] = 0;
		board[yCord][xCord].setBackground(Color.BLUE);
		frame.pack();

	}

	public void addObstacle(int xCord, int yCord) {
		//System.out.println("Obs " + xCord + " " + yCord);
		boardValues[yCord][xCord] = boardValues[yCord][xCord] + 3;
		if (boardValues[yCord][xCord] > 15) {
			boardValues[yCord][xCord] = 15;
		}
		update();
	}

	public boolean canMoveForward(int xCord, int yCord) {
		if (board[yCord][xCord].getBackground() == Color.RED) {
			return false;
		}
		return true;
	}

	public void addFreeSpace(int xCord, int yCord) {
		// System.out.println("Obs " + xCord + " " + yCord);
		boardValues[yCord][xCord] = boardValues[yCord][xCord] - 1;
		if (boardValues[yCord][xCord] < 0) {
			boardValues[yCord][xCord] = 0;
		}
		update();
	}

	public int[] findNextStep() {
		int closestX = 100;
		int closestY = 100;
		int counter = 0;
		for (int i = 0; i < 10; i++) {
			for (int j = 0; j < 10; j++) {
				if (Math.sqrt((closestX - xCord) * (closestX - xCord) + (closestY - yCord) * (closestY - yCord)) > Math.sqrt((j - xCord) * (j - xCord) + (i - yCord) * (i - yCord))) {
					if(j == 4 && i == 5){
						
					}
					if (exploredNeightbour(i, j) && board[i][j].getBackground() == Color.GRAY ) {
						closestX = j;
						closestY = i;
					}
				}
				//System.out.println("Done123: " + closestX + " " + closestY);
			}
			
		}
		
		int[] returnCord = new int[2];
		returnCord[0] = closestX;
		returnCord[1] = closestY;
		System.out.println("Done123: " + returnCord[0] + " " + returnCord[1]);
		if(!firstTime){
			int[] temp = djinkstra(returnCord);
			System.out.println("Done: " + xCord + " " + temp[0] + "       " + yCord + " " + temp[1]);
			returnCord[0] = temp[0];
			returnCord[1] = temp[1];
		}else{
			firstTime = false;
		}
		

		return returnCord;
	}

	private int[] djinkstra(int[] returnCord) {
		System.out.println("Target " + returnCord[0] + " " + returnCord[1]);
		String temp = xCord + "" + yCord;
		int indexRobot = Integer.parseInt(temp);
		System.out.println("Robot index " + indexRobot);

		int dist[] = new int[100];
		Integer previous[] = new Integer[100];

		for (int i = 0; i < 100; i++) {
			dist[i] = 100000;
			previous[i] = null;
		}
		dist[indexRobot] = 0;
		ArrayList<Node> Q = new ArrayList<Node>();
		for (int i = 0; i < 10; i++) {
			for (int j = 0; j < 10; j++) {
				//if (board[i][j].getBackground() != Color.RED) {
					Q.add(new Node(i, j, board[i][j]));
				//}
			}
		}
		temp = returnCord[0] + "" + returnCord[1];
		int indexTarget = Integer.parseInt(temp);
		while (!Q.isEmpty()) {
			Node n = getSmallest(dist, Q);
			Q.remove(n);
			if (n.getIndex() == indexTarget) {
				break;
			}

			if (n.getI() - 1 >= 0) {
				int cost = 1;
				if( board[n.getJ()][n.getI() -1].getBackground() == Color.RED){
					//System.out.println("RED " +(n.getI()-1) + " " + (n.getJ()));
					cost = 10000;
				}
				//System.out.println((n.getI()-1) + " " + (n.getJ()) + " " + board[n.getI()-1][n.getJ()].getBackground().toString() + " 0 " + boardValues[n.getI()-1][n.getJ()]);
				if(n.getI()-1 == 5 && n.getJ() == 9){
					//System.out.println(boardValues[n.getJ()][n.getI()-1]);
				}
				int alt = dist[n.getIndex()] + cost;
				if (alt < dist[getIndex(n.getI() - 1, n.getJ())]) { // Relax
					dist[getIndex(n.getI() - 1, n.getJ())] = alt;
					previous[getIndex(n.getI() - 1, n.getJ())] = n.getIndex();
				}
			}

			if (n.getI() + 1 < 10) {
				int cost = 1;
				if( board[n.getJ()][n.getI() +1].getBackground() == Color.RED){
					//System.out.println("RED "+ (n.getI()+1) + " " + (n.getJ()));
					cost = 10000;
				}
				//System.out.println((n.getI()+1) + " " + (n.getJ()) + " " + board[n.getJ()][n.getI()+1].getBackground().toString() + "1");
				
				int alt = dist[n.getIndex()] + cost;
				if (alt < dist[getIndex(n.getI() + 1, n.getJ())]) { // Relax
					dist[getIndex(n.getI() + 1, n.getJ())] = alt;
					previous[getIndex(n.getI() + 1, n.getJ())] = n.getIndex();
				}
			}
			if (n.getJ() + 1 < 10) {
				int cost = 1;
				if( board[n.getJ()+1][n.getI()].getBackground() == Color.RED){
					//System.out.println("RED "+ n.getI() + " " + (n.getJ()+1));
					cost = 10000;
				}
				//System.out.println((n.getI()) + " " + (n.getJ()+1) + " " + board[n.getI()][n.getJ()+1].getBackground().toString() + "2");
				int alt = dist[n.getIndex()] + cost;
				if (alt < dist[getIndex(n.getI(), n.getJ() + 1)]) { // Relax
					dist[getIndex(n.getI(), n.getJ() + 1)] = alt;
					previous[getIndex(n.getI(), n.getJ() + 1)] = n.getIndex();
				}
			}
			if (n.getJ() - 1 >= 0) {
				int cost = 1;
				if( board[n.getJ()-1][n.getI()].getBackground() == Color.RED){
					//System.out.println("RED "+ n.getI() + " " + (n.getJ()-1));
					cost = 10000;
				}
				//System.out.println((n.getI()+1) + " " + (n.getJ()) + " " + board[n.getI()][n.getJ()-1].getBackground().toString() + " 3" );
				int alt = dist[n.getIndex()] + cost;
				if (alt < dist[getIndex(n.getI(), n.getJ() - 1)]) { // Relax
					dist[getIndex(n.getI(), n.getJ() - 1)] = alt;
					previous[getIndex(n.getI(), n.getJ() - 1)] = n.getIndex();
				}
			}
			//System.out.println(Q.size());
		}
		int i = indexTarget;
		 int old = -1;
		 //System.out.println("indexTarget " + i);
		// System.out.println(previous[i]);
		while (previous[i] != null){
			System.out.println(i);
			Integer test = previous[i];
			//if(test != null){
				old = i;
			//}
			
			i = previous[i];                                   // Construct the shortest path with a stack S
		}

		int[] coord = new int[2];
		//System.out.println(old + " " + i);
		
		if(old == -1){
			coord[0] = 100;
			coord[1] = 100;
		}else{
			String s = "" + old;
			coord[0] = Integer.parseInt(s.substring(0, 1));
			coord[1] = Integer.parseInt(s.substring(1, s.length()));
		}
		
		//System.out.println(board[coord[0]][coord[1]].getBackground().toString());
		return coord;

	}

	private Node getSmallest(int[] dist, ArrayList<Node> q) {
		Node smallest = null;
		for (Node n : q) {
			if (smallest == null ) {
				smallest = n;
			} else if (dist[n.getIndex()] < dist[smallest.getIndex()] ) {
				smallest = n;
			}
		}
		return smallest;
	}

	private boolean exploredNeightbour(int i, int j) {
		
		if(board[i][j].getBackground() == Color.BLUE){
			return false;
		}
		if (i - 1 >= 0 && board[i - 1][j].getBackground() == Color.GREEN) {
			return true;
		}  
		if (i + 1 < 10 && board[i + 1][j].getBackground() == Color.GREEN) {
			return true;
		} 
		if (j + 1 < 10 && board[i][j + 1].getBackground() == Color.GREEN) {
			return true;
		} 
		if (j - 1 >= 0 && board[i][j - 1].getBackground() == Color.GREEN) {
			return true;
		}

		return false;
	}

	private int getIndex(int i, int j) {
		String temp = i + "" + j;
		return Integer.parseInt(temp);
	}

}
